package com.tedu.api.io;

import org.junit.Test;

import java.io.*;

/**
 * 标准IO流---目的：数据传输  输出文本 图片
 * java定义一套标准流--》数据传输--》创建流：直接创建某个流对象
 * 标准流规则①：方向划分  输入流和输出流
 *            输入流  读入---》文件---》相对于程序---》文件往程序走
 *            InputStream(抽象类：定义所有读的写法)【学习：子实现类】
 *            输出流：写出---》文件---》相对程序---》程序写出
 *            OutputStream(抽象类：定义所有写的方法)【学习：子实现类】
 *         ②：功能划分
 *         低级流：【节流的】：是建立在程序与数据源之间的”管道“
 *                  功能：负责搬运的数据流，输入流于输出流都有自己的低级流
 *                  特点：一个字节一个字节读或者写的方法
 *            FileOutputStream  低级流继承InputStream---文件输出流：写
 *            FileOutputStream  低级流继承OutputStream--文件输入流：读
 *         高级流【处理流】：不能独立存在，不能直接创建对象
 *                      功能：专门处理低级流以及其他高级流的流
 *                      特点：搬运数据时，实现具体功能：效率提高流
 *  ---总结：输出流和输入流，具备功能：低级流于高级流，实际使用，明确具体流，每个流都有自己的功能
 */
public class IOAPI {
    /**
     *                           文件输入流
     *             输入流     低级流---使用流
     * 标准流  方向     功能：       文件输出流：FileOutStream
     *          输出流          高级流
     *需求：写出一个文件 fos.txt
     *
     * FileOutputStream 构造器使用
     * new FileOutputStream("路径+文件全称")
     * new FileOutputStream("路径+文件全称"，boolean append)
     * 写出文件同时实现追加效果，第二个参数：true  追加
     *                               false 默认不追加
     * new FileOutputStream(File file,boolean append)
     * 写出文件：采用File传入路径+全称
     */
    @Test
    public void testFOS() throws IOException {
       // RandomAccessFile raf=new RandomAccessFile("fos.txt","rw");
        //低级流---文件输出流对象
        FileOutputStream fos=new FileOutputStream("fos.txt",true);
        //需求：fos.txt 增加一行文本,每次运行实现追加效果
        String say="独one无two";  //字符串有字符数组构成---数组的功能getBytes()转换为
        //输出--写功能：write(byte[] b)写出字节数组
        fos.write(say.getBytes("UTF8"));
        //必须关闭流---目的：节省内存开销
        fos.close();
    }

    /**
     * 文件输入流
     * FileInputStream 文件输入流
     * read() 返回一个读取一个字节---效率低
     * read(字节数组byte[] b)  返回一个”指定字节数组：空间大小“的读取---效率高
     * 需求：读入fos.txt文件内容
     */
    @Test
    public void testFIS() throws IOException {
        //创建文件输入流---读入：fos.txt
        FileInputStream fis=new FileInputStream("fos.txt");
        //读入效率高：创建字节数组-指定空间为：10KB
        byte[] data=new byte[1024*10];
        //读入操作：read(字节数组)  |  以10KB读入数据
        int len=fis.read(data);
        //写出：文本---字符串---针对流操作，提供构造器
        //                   文件按照”指定字节数组空间“写入程序中
        //                   从0开始写入程序，写入到-1结束
        //                   len:十进制转换为二进制，写入，不等-1，一直写入
        //一次性将给定数据按照字节数组指定空间大小，写出字符串
        String str=new String(data,0,len);
        System.out.println("打印Fos.txt文件："+str);
    }

    /**
     * 需求：利用标准流实现视频复制粘贴
     */
    @Test
    public void testCV() throws IOException {
        //1.从“复制文件。MP4” 复制 操作---读入
        FileInputStream fis=new FileInputStream("复制视频.mp4");
        //2.创建“新文件。MP4” 粘贴 操作---写出
      FileOutputStream fos=new FileOutputStream("新视频.mp4");
        //3.保存每次读取数据【字节量--int】
        int len=-1;
        //4.一直 从“复制文件。MP4”进行读入操作，不等于-1  一直读
        //(len=fis.read())!=-1
      while((len=fis.read())!=-1){//true
          //4.1同时 写出“新文件。MP4”
          fos.write(len);
      }
        //5.关闭流   ---测：效率低--正常播放
        fis.close(); fos.close();
    }

    /**
     * 需求：利用标准流实现复制粘贴视频---效率低
     *                             效率高---》空间执行为：自定 100KB
     *
     *【高级流】BufferedInputStream 缓冲输入流--提升效率--缓冲区：字节数组【长度按照文件大小合理分配】
     *        BufferedOutputStream  缓冲输出流--提示效率--缓冲区：字节数组【长度按照文件大小合理分配】
     * 高级流使用方式：①处理低级流，套在低级流上
     *               写法：new 高级流(传入低级流引用)
     *              ②直接使用高级流的方法
     *              ③高级流不能直接创建【不能独立存在】
     */
    @Test
    public void testCVS() throws IOException {
        //创建低级流：读入”复制视频“
        FileInputStream fis=new FileInputStream("复制视频.mp4");
        //创建高级流：套在低级流上【自带缓冲区：字节数组】
        BufferedInputStream bis=new BufferedInputStream(fis);

        //2.创建低级流：写出”高级视频。MP4“
        FileOutputStream fos=new FileOutputStream("高效视频.mp4");
        //2.创建高级流：套在低级流上【自带缓冲区：字节数组】
        BufferedOutputStream bos=new BufferedOutputStream(fos);

        //3.保存数据
        int len=-1;
        //4.高级流--低级流方法一致---read()读取内嵌缓冲区【字节数组】
        //高级流--低级流方法一致---write()写出内勤缓冲区【字节数组】
        //一直从”复制视频。MP4“读取数据，不等于-1，一直建
        //(len=bis.read())!=-1
        long start=System.currentTimeMillis();
        while((len=bis.read())!=-1){
            bos.write(len);
        }
        long end=System.currentTimeMillis();
        System.out.println("缓冲区【自带缓冲区】："+(end-start)+"毫秒数");
        //关闭流---高级流与低级流：都关---高级流间接性关闭低级流---关闭高级流
        bis.close();//高级流--缓冲输入流
        bos.close();//高级流--缓冲输出流
    }

    /**
     * 高级流---缓冲流【内嵌缓冲区】
     * BufferOutputStream  缓冲输出流
     *
     * 需求：通过缓冲输出流实现从程序写出文件：bos.txt，写出内容
     */
    @Test
    public void testBOS() throws IOException {
        //1.创建低级流--》bos.txt
        FileOutputStream fos=new FileOutputStream("bos.txt");
        //2.创建高级流---缓冲区：字节数组--合理【传输效率】
        BufferedOutputStream bos=new BufferedOutputStream(fos);
        //3.写出文本内容
        String str="50---- ";
        //4.写出到 bos.txt 文件中:字符串转成字节数组--写出
        bos.write(str.getBytes());
        //5.将缓冲区数据一次性写出 flush()  【立即写出】
        //bos.flush();
        //A        B
        bos.close();  //关闭流---一定把缓冲区数据全部写出

    }

    /**
     * 标准IO---成对【低级流+高级流】结合异常---数据传输---成功【异常需要捕获】
     * 重构  testBOS() 单元测试
     */
    @Test
   public void testBOSIO(){
        //1.置空流---提升所有流作用域：使用范围
        FileOutputStream fos=null;  //低级流：搬运数据
        BufferedOutputStream bos=null;//高级流：缓冲输出流
        //2.捕获流异常并且做出处理
        try {
            fos=new FileOutputStream("bos.txt");//低级流
            bos=new BufferedOutputStream(fos);//高级流:缓冲区：字节数组
            bos.write("d".getBytes());
            bos.flush();
        } catch (FileNotFoundException e){//IO流“小"异常
            e.printStackTrace();
        } catch (IOException e) {  //IO流 “中” 异常：小异常父类
            e.printStackTrace();
        } catch (Exception e){ //“大” 异常  Exception
             e.printStackTrace();
        } finally {  //一定执行代码块
            //3.关闭流--高级流--释放资源
            //判断：高级流不为null，关闭
            if(bos!=null)
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }
    }

    @Test
    public void testFOSIO(){
        FileOutputStream fos=null;
        BufferedOutputStream bos=null;
        try {
            fos=new FileOutputStream("bos.txt");
            bos=new BufferedOutputStream(fos);
            bos.write("a".getBytes());
            bos.flush();
        } catch (FileNotFoundException e){
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e){
            e.printStackTrace();
        } finally {
            if(bos!=null)
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }
    }

    @Test
    public void testFISIO(){
        FileOutputStream fos=null;
        BufferedOutputStream bos=null;
        try {
            fos=new FileOutputStream("bos.txt");
            bos=new BufferedOutputStream(fos);
            bos.write("c".getBytes());
            bos.flush();
        } catch (FileNotFoundException e){
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e){
            e.printStackTrace();
        } finally {
            if(bos!=null)
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }
    }

    @Test
    public void testCVIO(){
        FileOutputStream fos=null;
        BufferedOutputStream bos=null;
        try {
            fos=new FileOutputStream("bos.txt");
            bos=new BufferedOutputStream(fos);
            bos.write("d".getBytes());
            bos.flush();
        } catch (FileNotFoundException e){
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e){
            e.printStackTrace();
        } finally {
            if(bos!=null)
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }
    }
}


